library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;


entity sram_access IS
    GENERIC(
       num_requester_read      : natural := 4;
       num_requester_write      : natural := 4
    );
    PORT( 
       clk                : IN   std_logic;
       
       -- requests
       request_write      : IN   unsigned (num_requester_write-1 DOWNTO 0);
       request_read       : IN   unsigned (num_requester_read-1 DOWNTO 0);
       
       -- request data
       in_sram_wr_addr    : in std_logic_vector((18*num_requester_write)-1 DOWNTO 0);
       in_sram_wr_data    : in std_logic_vector((16*num_requester_write)-1 DOWNTO 0);
       in_sram_rq_addr    : in std_logic_vector((18*num_requester_read)-1 DOWNTO 0); 
       
       -- grants
       sram_scheduling_done_write : out std_logic;
       sram_scheduling_nr_write : out std_logic_vector (num_requester_write-1 DOWNTO 0);
       sram_scheduling_done_read : out std_logic;
       sram_scheduling_nr_read : out std_logic_vector (num_requester_read-1 DOWNTO 0);
       
       -- readout bus
       out_sram_read_addr     : out   std_logic_vector(17 DOWNTO 0);
       out_sram_read_data     : out   std_logic_vector(15 DOWNTO 0);
       out_sram_read_valid    : out   std_logic;
       
       -- physical 
       sram_addr     : out   std_logic_vector(17 DOWNTO 0);
       sram_data     : inout std_logic_vector(15 DOWNTO 0);
       sram_wren          : out   std_logic
       
    );
end sram_access;


architecture Behavioral of sram_access is
 
  -- wires
  signal scheduling_done_write : std_logic;
  signal scheduling_nr_write : std_logic_vector (num_requester_write-1 DOWNTO 0);
  signal scheduling_done_read : std_logic;
  signal scheduling_nr_read : std_logic_vector (num_requester_read-1 DOWNTO 0);
 
  signal out_sram_wr_addr     : std_logic_vector(17 DOWNTO 0);
  signal out_sram_wr_data     : std_logic_vector(15 DOWNTO 0);
  signal out_sram_rq_addr     : std_logic_vector(17 DOWNTO 0);
  
  signal start_schedule_read      :  std_logic;
  signal start_schedule_write     :  std_logic;
 
  component arbiter IS
    GENERIC(
       num_requester      : natural := 4
    );
    PORT( 
       clk                : IN   std_logic;
       request            : IN   unsigned (num_requester-1 DOWNTO 0);
       start_schedule     : IN   std_logic;
       schedule_nr        : OUT   std_logic_vector (num_requester-1 DOWNTO 0);
       scheduling_done    : OUT   std_logic           
    );
  end component;
  
  component sram_write_mux IS
    GENERIC(
       num_requester      : natural := 4
    );
    PORT( 
       in_sram_wr_addr    : in std_logic_vector((18*num_requester)-1 DOWNTO 0);
       in_sram_wr_data    : in std_logic_vector((16*num_requester)-1 DOWNTO 0);
       schedule_nr        : in   std_logic_vector (num_requester-1 DOWNTO 0);
       out_sram_wr_addr     : out   std_logic_vector(17 DOWNTO 0);
       out_sram_wr_data     : out   std_logic_vector(15 DOWNTO 0)
    );
  end component;
  
  component sram_read_mux IS
    GENERIC(
       num_requester      : natural := 4
    );
    PORT( 
       in_sram_rq_addr    : in std_logic_vector((18*num_requester)-1 DOWNTO 0);
       schedule_nr        : in   std_logic_vector (num_requester-1 DOWNTO 0);
       out_sram_rq_addr     : out   std_logic_vector(17 DOWNTO 0)
    );
  end component;
  
  
  component sram_rw_unit IS
    PORT( 
       clk                : IN   std_logic;
       in_sram_wr_addr     : in   std_logic_vector(17 DOWNTO 0);
       in_sram_wr_data     : in   std_logic_vector(15 DOWNTO 0);
       in_sram_rq_addr     : in   std_logic_vector(17 DOWNTO 0);
       scheduling_done_read    : in   std_logic;
       scheduling_done_write    : in   std_logic;
       start_schedule_read      : out   std_logic;
       start_schedule_write     : out   std_logic;
       out_sram_read_addr     : out   std_logic_vector(17 DOWNTO 0);
       out_sram_read_data     : out   std_logic_vector(15 DOWNTO 0);
       out_sram_read_valid    : out   std_logic;
       sram_addr     : out   std_logic_vector(17 DOWNTO 0);
       sram_data     : inout std_logic_vector(15 DOWNTO 0);
       sram_wren          : out   std_logic
    );
  end component;

  
 
    
begin
  
  
  sram_scheduling_done_write <= scheduling_done_write;
  sram_scheduling_nr_write <= scheduling_nr_write;
  sram_scheduling_done_read <= scheduling_done_read;
  sram_scheduling_nr_read <= scheduling_nr_read;
  
        
  arbiter_write : arbiter 
  generic map(
     num_requester      => num_requester_write 
  )
  port map ( 
     clk                => clk,
     request            => request_write,
     start_schedule     => start_schedule_write,
     schedule_nr        => scheduling_nr_write,
     scheduling_done    => scheduling_done_write      
  );
  
  arbiter_read : arbiter 
  generic map(
     num_requester      => num_requester_read 
  )
  port map ( 
     clk                => clk,
     request            => request_read,
     start_schedule     => start_schedule_read,
     schedule_nr        => scheduling_nr_read,
     scheduling_done    => scheduling_done_read      
  );


  sram_write_mux1 : sram_write_mux 
  GENERIC map(
       num_requester      => num_requester_write 
    )
  PORT map( 
       in_sram_wr_addr    => in_sram_wr_addr,
       in_sram_wr_data    => in_sram_wr_data,
       schedule_nr        => scheduling_nr_write,
       out_sram_wr_addr   => out_sram_wr_addr,
       out_sram_wr_data   => out_sram_wr_data
  );
  
  sram_read_mux1 : sram_read_mux
  GENERIC map(
       num_requester      => num_requester_read
  )
  PORT map( 
       in_sram_rq_addr    => in_sram_rq_addr,
       schedule_nr        => scheduling_nr_read,
       out_sram_rq_addr   => out_sram_rq_addr
  );
  
  
  sram_rw_unit1 : sram_rw_unit
  PORT map( 
       clk                => clk,
       in_sram_wr_addr     => out_sram_wr_addr,
       in_sram_wr_data     => out_sram_wr_data,
       in_sram_rq_addr     => out_sram_rq_addr,
       scheduling_done_read  => scheduling_done_read,
       scheduling_done_write  => scheduling_done_write,
       start_schedule_read    => start_schedule_read,
       start_schedule_write   => start_schedule_write,
       out_sram_read_addr     => out_sram_read_addr,
       out_sram_read_data     => out_sram_read_data,
       out_sram_read_valid    => out_sram_read_valid, 
       sram_addr     => sram_addr,
       sram_data     => sram_data,
       sram_wren     => sram_wren
  );
 
  

  


end Behavioral;










